﻿using System.Collections.Generic;
using UnityEngine;

namespace Share.Audio
{
    public class AudioGroup : AudioBase
    {
        private Queue<AudioSource> audioSourcePool = new Queue<AudioSource>();
        private List<AudioSource> activeSources = new List<AudioSource>();
        private const int InitialPoolSize = 5;
        private void Awake()
        {
            InitializePool();
        }

        private void InitializePool()
        {
            for (int i = 0; i < InitialPoolSize; i++)
            {
                CreateNewAudioSource();
            }
        }

        private AudioSource CreateNewAudioSource()
        {
            AudioSource source = AudioManager.AddAudioSource(gameObject);
            source.playOnAwake = false;
            source.loop = false;
            audioSourcePool.Enqueue(source);
            return source;
        }

        public void Play(string name, float volumeScale = 1f)
        {
            if (Volume <= 0)
                return;
            var clip = ObjectMgr.Instance.CreateAudioClip(name);
            Play(ObjectPoolManager.Instance.GetFreeAudioClipFromPool(clip), volumeScale);
        }
        public void Play(AudioClip clip, float volumeScale = 1f)
        {
            if (Volume <= 0)
                return;
            if (clip == null) return;

            AudioSource source = GetAvailableSource();
            if (source == null)
            {
                source = CreateNewAudioSource();
            }

            source.clip = clip;
            source.volume = Volume * volumeScale;
            source.Play();
            activeSources.Add(source);

        }

        private AudioSource GetAvailableSource()
        {
            while (audioSourcePool.Count > 0)
            {
                AudioSource source = audioSourcePool.Dequeue();
                if (!source.isPlaying)
                {
                    return source;
                }
                activeSources.Add(source);
            }
            return null;
        }

        public void StopAll()
        {
            foreach (var source in activeSources)
            {
                if (source.isPlaying)
                {
                    source.Stop();
                    ReturnSourceToPool(source);
                }
            }
        }

        private void ReturnSourceToPool(AudioSource source)
        {
            activeSources.Remove(source);
            audioSourcePool.Enqueue(source);
        }

        public override void SetVolume(float newVolume)
        {
            base.SetVolume(newVolume);
            Volume = Mathf.Clamp01(newVolume);
            foreach (var source in activeSources)
            {
                source.volume = Volume;
            }
        }

        private void Update()
        {
            CleanupFinishedSources();
        }

        public void ReleaseUnusedSources()
        {
            while (audioSourcePool.Count > InitialPoolSize)
            {
                AudioSource source = audioSourcePool.Dequeue();
                Destroy(source.gameObject);
            }
        }

        private void CleanupFinishedSources()
        {
            for (int i = activeSources.Count - 1; i >= 0; i--)
            {
                if (!activeSources[i].isPlaying)
                {
                    ReturnSourceToPool(activeSources[i]);
                }
            }
        }
    }
}
